<?php


use App\Models\BotModel;

#----------------
# bot_init
#----------------

/**
 * @title 返回剩余可使用端口号
 * @return array
 */
function check_surplus_port()
{
    $BotModel = new BotModel();
    $ports_allow = range($BotModel->port_range_min, $BotModel->port_range_max);
    $ports_used = array_column($BotModel->getUsePort('port'), 'port');
    $surplus = array_diff($ports_allow, $ports_used);
    return $surplus;
}

/**
 * @title 返回设备详情
 * @param $port
 * @return mixed
 * @throws ErrorException
 */
function check_port_used($port)
{
    $BotModel = new BotModel();
    $devices = $BotModel->getRows('port', $port);
    if (!$devices) {
        throw new ErrorException('port device does not exist');
    }
    return $devices;
}

/**
 * @title 初始化设备文件
 * @param $port 端口号
 * @param $device 设备名
 * @return bool
 * @throws ErrorException
 */
function ready_device($port, $device)
{
    $package_path = dirname(ROOTPATH) . env('bot.path.root') . env('bot.path.package');
    $device_path = dirname(ROOTPATH) . env('bot.path.root') . env('bot.path.devices') . $device . '/';
    if (!is_readable($device_path)) {
        is_file($device_path) or mkdir($device_path, 0755);
    }

    $ready_res = $package_path . $device . env('bot.pack.suffix');
    $used_res = $device_path . $port . env('bot.pack.suffix');
    if (!copy($ready_res, $used_res)) {
        throw new ErrorException('initialization failed');
    }
    if (!unzip($used_res, $device_path . $port) || !chmod($device_path . $port, 0755)) {
        throw new ErrorException('initialization failed');
    }
    array_map(function ($vl) {
        chmod($vl, 0755);
    }, glob($device_path . $port . '/*'));
    unlink($used_res);
    return true;
}

/**
 * @title 删除设备文件
 * @param $port
 * @return bool
 * @throws ErrorException
 */
function del_device($port)
{
    $devices = check_port_used($port);
    $device_dir = dirname(ROOTPATH) . env('bot.path.root') . env('bot.path.devices') . $devices['device'] . '/' . $port . '/';
    #quit
    pclose(popen("sh {$device_dir}quit.sh", 'r'));
    rm_dir($device_dir);
    return true;
}

/**
 * @title 初始化设备
 * @param $port
 * @return bool
 * @throws ErrorException
 */
function init_device($port)
{
    $devices = check_port_used($port);
    $device_dir = dirname(ROOTPATH) . env('bot.path.root') . env('bot.path.devices') . $devices['device'] . '/' . $port . '/';
    $init_devices_data = [
        [
            'file_name' => 'config.yml',
            'peg' => explode(',', env('bot.replace.config')),
            'replace' => [
                $devices['account'],
                $devices['port'],
                env('bot.push_notify_url'),
            ]
        ],
        [
            'file_name' => 'signin.sh',
            'peg' => explode(',', env('bot.replace.signin')),
            'replace' => [
                $device_dir,
            ]
        ],
        [
            'file_name' => 'quit.sh',
            'peg' => explode(',', env('bot.replace.quit')),
            'replace' => [
                $devices['port'],
                $device_dir,
            ]
        ],
    ];

    foreach ($init_devices_data as $v) {
        #init ready start
        $device_dir_file = $device_dir . $v['file_name'];
        $content = file_get_contents($device_dir_file);
        $write_content = str_replace($v['peg'], $v['replace'], $content);
        file_put_contents($device_dir_file, $write_content);# ready end
    }

    return true;
}

/**
 * @title 获取设备二维码
 * @param $port
 * @return string
 * @throws ErrorException
 */
function device_qrcode($port)
{
    $devices = check_port_used($port);
    $device_dir = dirname(ROOTPATH) . env('bot.path.root') . env('bot.path.devices') . $devices['device'] . '/' . $port . '/';
    #initing signin
    pclose(popen("sh {$device_dir}signin.sh", 'r'));
    $qrcode_dir = $device_dir . 'qrcode.png';
    $i = 0;
    while (!is_readable($qrcode_dir)) {
        if ($i > 5) break;
        usleep(500000);
        $i++;
    }

    $base64_img = file_to_base64img($device_dir . 'qrcode.png');
    unlink($device_dir . 'qrcode.png');
    return $base64_img;
}

/**
 * @title 设备退出登录
 * @param $port
 * @return string
 * @throws ErrorException
 */
function device_quit_account($port)
{
    $devices = check_port_used($port);
    $device_dir = dirname(ROOTPATH) . env('bot.path.root') . env('bot.path.devices') . $devices['device'] . '/' . $port . '/';
    #quit
    pclose(popen("sh {$device_dir}quit.sh", 'r'));
    return true;
}
#----------------
# bot_interflow
#----------------

/**
 * @title BOT请求方式POST
 * @param $port
 * @param $opts
 * @param $api_path
 * @return mixed
 */
function curl_post($port, $opts , $api_path = 'send_private_msg')
{
    $client = \Config\Services::curlrequest();
    $url = 'http://127.0.0.1:{{PORT}}/'.$api_path;
    $form_params = [
        'form_params' => $opts,
    ];
    $response = $client->post(str_replace('{{PORT}}', $port, $url), $form_params);
    return $response->getBody();
}

/**
 * @title BOT请求方式GET
 * @param $port
 * @param $opts
 * @param $api_path
 * @return mixed
 */
function curl_get($port, $opts , $api_path = 'get_status')
{
    $client = \Config\Services::curlrequest();
    $url = 'http://127.0.0.1:{{PORT}}/'.$api_path;
    $form_params = [
        'form_params' => $opts,
    ];
    if (empty($opts))$form_params = [];

    $response = $client->get(str_replace('{{PORT}}', $port, $url), $form_params);
    return $response->getBody();
}

/**
 * @title BOT私聊发送
 * @param $params
 * @return mixed
 * @throws ErrorException
 */
function send_private_msg($params)
{
    $validation = \Config\Services::validation();
    $devices = check_port_used($params['port']);
    switch ($devices['device']) {
        case 'QQ':
            //$validation->reset();
            if (!$validation->run($params, 'account_message')) {
                throw new ErrorException(implode('\\', array_values($validation->getErrors())));
            }
            $opts = [
                'user_id' => $params['account'],
                'message' => $params['message'],
            ];
            break;
        case 'WX':
            throw new ErrorException('wechat equipment is still under internal test');
            break;
        default:
            throw new ErrorException('this device is not recognized//:' . $devices['device']);
            break;
    }

    return curl_post($devices['port'], $opts);
}

/**
 * @title 获取BOT状态
 * @param $params
 * @return mixed
 * @throws ErrorException
 */
function get_status($params)
{
    $validation = \Config\Services::validation();
    $devices = check_port_used($params['port']);
    switch ($devices['device']) {
        case 'QQ':
            break;
        case 'WX':
            throw new ErrorException('wechat equipment is still under internal test');
            break;
        default:
            throw new ErrorException('this device is not recognized//:' . $devices['device']);
            break;
    }

    return curl_get($devices['port'], []);

}


function push_notify($account, $opts)
{
    $BotModel = new BotModel();
    $devices = $BotModel->getRows('account', $account);
    $client = \Config\Services::curlrequest();
    $url = $devices['domain'].'/api/botMessage';#push url
    $form_params = [
        'form_params' => $opts,
    ];
    $client->post($url, $form_params);
    return true;
}